package fr.lip6.meta.tools;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;

import fr.lip6.meta.ple.constraintsextraction.constraint.Constraint;
import fr.lip6.meta.ple.featureIdentification.Feature;
import fr.lip6.meta.ple.generation.fh.java.ProductLineConstructionFHJava;
import fr.lip6.meta.ple.generation.strategy.ProductLineConstructionStrategy;

public class ModelXML extends ProductLineConstructionFHJava implements ProductLineConstructionStrategy{

	private PrintStream out;
	private Collection<Feature> features;
	private int hieractchie = 1;

	public String getInd(){
		String ind = "";
		for(int i = 0 ; i < hieractchie ; i++)
			ind += "\t";
		return ind;
	}

	public void generateFeatureModel(Collection<Feature> features, 
			ArrayList<Constraint> rules,String model_dir) {
		this.features = features;
		String rep1 = model_dir;
		File repit = new File (rep1);
		deleteRecursive(repit);
		repit.mkdirs();
		File dotFile = new File(rep1+"model.xml");
		FileOutputStream fout;

		try {
			fout = new FileOutputStream(dotFile);
			out = new PrintStream(fout);
			out.print("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"+"\n");
			out.println(getInd() + "<featureModel>");
			hieractchie ++;
			out.println(getInd() + "<struct>");
			hieractchie ++;
			out.println(getInd() +"<and abstract=\"true\" mandatory=\"true\" name=\"SPLConstruction\">");
			Feature f = features.iterator().next();
			printNoeud(f);
			out.println(getInd() +"</and>"); hieractchie --;
			out.println(getInd() +"</struct>"); hieractchie -- ; 
			out.println(getInd() +"</featureModel>");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

	}

	private void printNoeud(Feature current) {
		hieractchie ++;
		if(current.getProdIds().size() > 1) {
			String prods =  current.getProdIds().toString();
			prods = prods.replace('[', ' ').replace(']', ' ').replace(',', ' ').replaceAll(" ","");
			ArrayList<Feature> children = getChildren(current);
			boolean isMandatory = notFinProduct(current, children);
			if(isMandatory){
				out.println(getInd() +"<feature hidden=\"true\" mandatory=\"true\" name="+"\""+current.getId()+"\""+" />");
				out.println(getInd() +"<alt abstract=\"true\" mandatory=\"true\" name=\"A"+ prods +"\">");

			}else {
				out.println(getInd() +"<feature mandatory=\"true\" name="+"\""+current.getId()+"\""+" />");
				out.println(getInd() +"<alt abstract=\"true\" name=\"A"+ prods +"\">");
			}

			for(Feature f : children) {
				if(f.getProdIds().size() > 1) {
					hieractchie ++;
					out.println(getInd() +"<and abstract=\"true\" mandatory=\"true\" name=\""+ f.getId() + prods +"\">");
					printNoeud(f);
					hieractchie --;
					out.println(getInd() +"</and>");
				}else {
					printNoeud(f);
				}
			}
			hieractchie --;
			out.println(getInd() +"</alt>");
		} else {
			out.println(getInd() +"<feature name="+"\""+current.getId()+"\""+" />");
		}
		hieractchie --;
	}

	private boolean notFinProduct(Feature current, ArrayList<Feature> children) {
		LinkedHashSet<Integer> prod = current.getProdIds();
		LinkedHashSet<Integer> prodChild = new LinkedHashSet<Integer>();
		for(Feature f : children){
			prodChild.addAll(f.getProdIds());
		}

		for(Integer i : prod){
			if(!prodChild.contains(i)) return false;
		}

		return true;
	}

	private ArrayList<Feature> getChildren(Feature current){
		ArrayList<Feature> f = new ArrayList<Feature>();
		for(Feature c : features) {
			if(c.getIdAnc() != null && c.getIdAnc().equals(current.getId())) f.add(c);
		}
		return f;
	}
}
